using System.Collections.Generic;
using AhpilyServer;
using AhpilyServers;
using GameServer.Cache;
using GameServer.Cache.Fight;
using GameServer.Model;
using Protocol.Code;
using Protocol.Constant;
using Protocol.Dto.Fight;

namespace GameServer.Logic
{

    public class FightHandler : IHeadler
    {
        public FightCache fightCache = Caches.Fight;
        public UserCache userCache = Caches.User;

        public void OnDisconnect(ClientPeer client)
        {
            leave(client);
        }

        public void OnReceive(ClientPeer client, int SubCode, object value)
        {
            switch (SubCode)
            {
                case FightCode.GRAB_LANDLORD_CREQ:
                    // true---抢地主
                    bool result = (bool)value;
                    grabLandLord(client, result);
                    break;
                case FightCode.DEAL_CREQ:
                    deal(client, value as DealDto);
                    break;
                case FightCode.PASS_CREQ:
                    pass(client);
                    break;
                default:
                    break;
            }
        }
        /// <summary>
        /// 用户离开
        /// </summary>
        private void leave(ClientPeer client)
        {
            SingleExcute.Instance.Excute(() =>
            {
                if (userCache.IsOnline(client) == false)
                {
                    return;
                }
                int userId = userCache.GetId(client);
                if (false == fightCache.IsFighting(userId))
                {
                    return;
                }
                FightRoom room = fightCache.GetRoomByUid(userId);

                room.LeaveUIdList.Add(userId);
                brocast(room, OpCode.FIGHT, FightCode.LEAVE_BRO, userId);

                // 所有人都离开了
                if (room.LeaveUIdList.Count == 3)
                {
                    // 给逃跑者添加逃跑场
                    for (int i = 0; i < room.LeaveUIdList.Count; i++)
                    {
                        UserModel um = userCache.GetModelById(room.LeaveUIdList[i]);
                        um.RunCount++;
                        um.Been -= room.Mutiple * 1000 * 2;
                        if (um.Been < 0)
                        {
                            um.Been = 0;
                        }
                        um.Exp += 0;
                        userCache.Update(um);
                    }
                    // 在缓存层销毁房间数据
                    fightCache.Destory(room);
                }
            });
        }
        private void pass(ClientPeer client)
        {
            SingleExcute.Instance.Excute(() =>
            {
                if (userCache.IsOnline(client) == false)
                {
                    return;
                }
                int userId = userCache.GetId(client);
                FightRoom room = fightCache.GetRoomByUid(userId);
                // 分两种情况
                // 我的牌最大,还是我出
                if (room.roundModel.BiggestUId == userId)
                {
                    client.Send(OpCode.FIGHT, FightCode.PASS_SRES, -1);
                    return;
                }
                else
                {
                    //可以不出
                    client.Send(OpCode.FIGHT, FightCode.PASS_SRES, 0);
                    turn(room);
                }

            });
        }
        /// <summary>
        /// 出牌的处理
        /// </summary>
        private void deal(ClientPeer client, DealDto dto)
        {
            SingleExcute.Instance.Excute(() =>
            {
                if (userCache.IsOnline(client) == false)
                {
                    return;
                }
                int userId = userCache.GetId(client);
                if (userId != dto.UserId)
                {
                    return;
                }
                FightRoom room = fightCache.GetRoomByUid(userId);
                // 如果玩家退出
                if (room.LeaveUIdList.Contains(userId))
                {
                    // 转换出牌
                    turn(room);
                }
                bool canDeal = room.DealCard(dto.Type, dto.Weight, dto.Length, userId, dto.SelectCardList);
                if (canDeal == false) // 比上一次出的牌小
                {
                    // 重新出牌
                    client.Send(OpCode.FIGHT, FightCode.DEAL_SRES, -1);
                    return;
                }
                else if (dto.IsRegular == false) // 出牌不符合规则
                {
                    // 重新出牌
                    client.Send(OpCode.FIGHT, FightCode.DEAL_SRES, -2);
                    return;
                }
                else
                {
                    // 给客户端发送出牌成功的消息
                    client.Send(OpCode.FIGHT, FightCode.DEAL_SRES, 0);

                    // 检测剩余手牌,手牌数为0,游戏结束
                    List<CardDto> remainCardList = room.GetPlayerModel(userId).CardList;
                    // 广播 
                    dto.RemainCardList = remainCardList;
                    brocast(room, OpCode.FIGHT, FightCode.DEAL_BRO, dto);

                    if (dto.Type == CardType.BOOM || dto.Type == CardType.JOKER_BOOM)
                    {
                        // 广播倍数增加的消息
                        int cardType = dto.Type;
                        brocast(room, OpCode.FIGHT, FightCode.CHAGE_MUTIPLE_SRES, cardType);
                    }

                    if (remainCardList.Count == 0)
                    {
                        // Game Over
                        gameOver(userId, room);
                    }
                    else
                    {
                        // 转换出牌                    
                        turn(room);
                    }
                }
            });
        }
        /// <summary>
        /// 游戏结束
        /// </summary>
        private void gameOver(int userId, FightRoom room)
        {
            int winIdentity = room.GetPlayerIdentity(userId);
            int winBeen = room.Mutiple * 1000;
            List<int> winUIds = room.GetSameIdentityUids(winIdentity);

            // 给胜者增加胜场
            for (int i = 0; i < winUIds.Count; i++)
            {
                UserModel um = userCache.GetModelById(winUIds[i]);
                um.WinCount++;

                // 农民平均分欢乐豆, 地主全拿
                if (winIdentity == Identity.LANDLOAD)
                    um.Been += winBeen;
                else
                    um.Been += winBeen / 2;

                um.Exp += 100;
                //int maxExp = um.Lv * 100;
                while (um.Lv * 100 <= um.Exp)
                {
                    um.Exp -= um.Lv * 100;
                    um.Lv++;
                }
                userCache.Update(um);
            }
            // 给负者添加负场
            List<int> loseUIds = room.GetDifferentIdentityUids(winIdentity);
            for (int i = 0; i < loseUIds.Count; i++)
            {
                UserModel um = userCache.GetModelById(loseUIds[i]);
                um.LoseCount++;

                // 农民平均分输的欢乐豆, 地主全输
                if (winIdentity != Identity.LANDLOAD)
                    um.Been -= winBeen;
                else
                    um.Been -= winBeen / 2;
                //um.Been -= winBeen;

                if (um.Been <= 0)
                {
                    // 不让豆子出现负数的情况
                    um.Been = 0;
                }
                um.Exp += 10;
                while (um.Lv * 100 <= um.Exp)
                {
                    um.Exp -= um.Lv * 100;
                    um.Lv++;
                }
                userCache.Update(um);
            }
            // 给逃跑者添加逃跑场
            for (int i = 0; i < room.LeaveUIdList.Count; i++)
            {
                UserModel um = userCache.GetModelById(room.LeaveUIdList[i]);
                um.RunCount++;
                um.Been -= winBeen;
                um.Exp += 0;
                while (um.Lv * 100 <= um.Exp)
                {
                    um.Exp -= um.Lv * 100;
                    um.Lv++;
                }
                userCache.Update(um);
            }

            // 给客户端发消息,谁赢了, 加多少豆子?
            OverDto dto = new OverDto();
            dto.WinIdentity = winIdentity;
            dto.WinUIdList = winUIds;
            dto.BeenCount = winBeen;
            brocast(room, OpCode.FIGHT, FightCode.OVER_BRO, dto);

            // 在缓存层销毁房间数据
            fightCache.Destory(room);
        }

        /// <summary>
        /// 转换出牌
        /// </summary>
        private void turn(FightRoom room)
        {
            int nextUId = room.Turn();
            if (room.IsOffline(nextUId))
            {
                // 已经离开
                turn(room);
            }
            else
            {
                //ClientPeer nextClient = userCache.GetClientPeer(nextUId);
                //nextClient.Send(OpCode.FIGHT, FightCode.TURN_DEAL_BRO, nextUId);
                brocast(room, OpCode.FIGHT, FightCode.TURN_DEAL_BRO, nextUId);
            }
        }
        /// <summary>
        /// 抢地主的处理
        /// </summary>
        private void grabLandLord(ClientPeer client, bool result)
        {
            SingleExcute.Instance.Excute(() =>
            {
                if (userCache.IsOnline(client) == false)
                {
                    return;
                }
                int userId = userCache.GetId(client);
                FightRoom room = fightCache.GetRoomByUid(userId);

                if (result == true)
                {
                    // 抢
                    room.SetLandLoad(userId);
                    // 告诉每个玩家谁当了地主
                    // 给地主发底牌
                    GrabDto dto = new GrabDto(userId, room.TableCardList, room.GetUserCards(userId));
                    brocast(room, OpCode.FIGHT, FightCode.GRAB_LANDLORD_BRO, dto);
                    // 发送一个出牌的命令
                    brocast(room, OpCode.FIGHT, FightCode.TURN_DEAL_BRO, userId);

                }
                else
                {
                    // 不抢
                    int nextUId = room.GetNextUId(userId);
                    brocast(room, OpCode.FIGHT, FightCode.TURN_GRAB_BRO, nextUId);
                }

            });
        }

        /// <summary>
        /// 开始战斗
        /// </summary>
        public void StartFight(List<int> uidList)
        {
            SingleExcute.Instance.Excute(() =>
            {
                // 创建战斗房间
                FightRoom room = fightCache.Create(uidList);
                room.InitPlayerCards();
                room.Sort();
                // 发送给每一个客户端 他自身有什么牌
                foreach (int uid in uidList)
                {
                    ClientPeer client = userCache.GetClientPeer(uid);
                    List<CardDto> cardList = room.GetUserCards(uid);
                    //int[] cardIds = new int[17];
                    client.Send(OpCode.FIGHT, FightCode.GET_CARD_SRES, cardList);
                }
                // 发送开始抢地主的响应
                int firstUserId = room.GetFirstUId();
                brocast(room, OpCode.FIGHT, FightCode.TURN_GRAB_BRO, firstUserId, null);
            });
        }
        /// <summary>
        /// 广播
        /// </summary>
        private void brocast(FightRoom room, int opCode, int subCode, object value, ClientPeer curClient = null)
        {
            SocketMsg msg = new SocketMsg(opCode, subCode, value);
            byte[] data = EncodeTools.EncodeMsg(msg);
            byte[] packet = EncodeTools.EncodePacket(data);
            foreach (var player in room.PlayerList)
            {
                if (userCache.IsOnline(player.UserId))
                {
                    ClientPeer client = userCache.GetClientPeer(player.UserId);
                    if (client == curClient)
                        continue;
                    client.Send(packet);
                }

            }
        }
    }
}
